import axios from 'axios';
import Raven from 'raven-js';
import { MessageBox, Message } from 'element-ui';
import store from '../../store';
import ElMessage from '@/utils/message';
import { getToken } from '@/utils/auth';
import { notAuthWord, aesEncode, aesDecode } from '@/utils/string';
import { decodeField } from '../secret/secretField';
import { SECRET_KEY } from '@/utils/const';

const { BASE_API, rapConfig, REQUEST_TIME, AES_OPEN, EXCLUDE_SECRET_URL = [] } = process.env;
let params = null;

// 创建axios实例
const service = axios.create({
  baseURL: BASE_API, // api 的 base_url
  timeout: 50000, // 请求超时时间
  headers: {
    'Content-Type': 'application/json'
  },
  transformRequest: [(data, headers) => {
    if (headers['Content-Type'] === 'multipart/form-data') return data;
    return typeof data === 'string' ? data : JSON.stringify(data);
  }] // 参数转换NODE_ENV
});

// 设置默认的请求时间间隙
// axios.defaults.retry = 5;
// axios.defaults.retryDelay = 1000;

// RAP拦截处理
if (process.env.NODE_ENV === 'development') {
  const rapFun = () => require('./rap.js');
  const rap = rapFun().default;
  rap.updateConfig(rapConfig);
  service.interceptors.request.use(config => rap.onFulfilled(config), rap.onRejected);
}
if (AES_OPEN && window && !window.aesDecode) {
  window.aesDecode = (str) => {
    const decodeStr = aesDecode(str, SECRET_KEY);
    try {
      return typeof decodeStr === 'string' ? JSON.parse(decodeStr) : decodeStr;
    } catch (error) {
      return decodeStr;
    }
  };
}
// request拦截器, 先于RAP拦截
service.interceptors.request.use(config => {
  params = config.params;
  const token = store.getters.token || getToken(); // 获取本地Token
  if (token) {
    config.headers.common['token'] = token; // 让每个请求携带自定义token 请根据实际情况自行修改
  }
  // 针对特定接口设置超时时间
  const longTimeUrls = ['admin/commerce/goodsOrder/check'];
  if (longTimeUrls.includes(config.url)) {
    config.timeout = 120000;
  }
  config.metadata = { startTime: new Date() };
  if (AES_OPEN && config.data) {
    const is_exclude = EXCLUDE_SECRET_URL.some(item => config.url.includes(item));
    if (!is_exclude) {
      const isStr = typeof config.data === 'string' || typeof config.data === 'number';
      config.data = aesEncode(isStr ? config.data : JSON.stringify(config.data), SECRET_KEY);
    }
  }
  return config;
}, error => {
  // Do something with request error
  console.log(error); // for debug
  Promise.reject(error);
});

// response 拦截器，先于AWS拦截
service.interceptors.response.use(response => {
  /**
   * code为非20000是抛错 可结合自己业务进行修改
   */
  if (AES_OPEN && response.data && typeof response.data === 'string') {
    const decodeStr = aesDecode(response.data, SECRET_KEY);
    try {
      response.data = typeof decodeStr === 'string' ? JSON.parse(decodeStr) : decodeStr;
    } catch (error) {
      response.data = decodeStr;
    }
  }
  const res = response.data;
  decodeField(response);
  // 501 为业务单独处理的错误
  if (response.status === 501 || res.code === 501) {
    return response.data;
  }
  if (response.status !== 200 || res.code !== 200) {
    console.error(`Status Error: ${res.message}`);
    const message = res.message;
    if ((response.status === 403 || res.code === 403) && response.config.url.indexOf('/admin/medium/filter') < 0 && response.config.url.indexOf('admin/commerce/goodsOrder/check') < 0) {
      if (!response.config.params || !response.config.params.notShowNoAuthTip) {
        ElMessage.warning(notAuthWord(response.config.url) + res.message);
      }
    }

    const resetMsg = store.state.app.message;

    const errCodes = [504, 403, 505, 608];
    if (response.code !== 200 && !errCodes.includes(res.code) && res.message !== resetMsg) {
      const whiteList = [
        '/dingTalk/login',
        '/fieldConditionOption',
        '/admin/resource/info',
        'admin/publish/update/status',
        'admin/flyUser/relateSupplier',
        'admin/flyUser/setStatus',
        'admin/processManagement/sendMsg',
        'admin/publish/check'
      ];
      const msgHide = whiteList.some(i => response.config.url.indexOf(i) >= 0);
      // 特殊情况：只处理502并且调整成弹窗报错
      const specialUrls = ['/admin/financialFlow/batchWriteOff'];
      const isSpecial = specialUrls.some(i => response.config.url.indexOf(i) >= 0) && res.code === 502;
      if (!msgHide && isNaN(Number(res.message)) && res.message !== '验证码有误') {
        // 操作错误换行提示
        if (/\r\n/g.test(res.message)) {
          res.message = res.message.split('\r\n').map(item => {
            return '<span style="display:inline-block;max-width:1000px;">' + item + '</span>';
          }).join('<br/>');
        }
        // 用于区分如果是忘记密码发送验证码和重置密码不展示message提示，直接在表单提示
        !isSpecial && Message({
          type: 'error',
          dangerouslyUseHTMLString: true,
          message: res.message,
          customClass: 'http-error-message'
        });
        store.dispatch('SetMsg', res.message);
      }
      setTimeout(() => {
        store.dispatch('SetMsg', '');
      }, 2000);
    }

    if (res && res.code === 505) {
      // 重复提交修改审批流程
      res.message = '当前页面数据已变更无法操作，页面将自动刷新并获取最新数据';
      Message({
        type: 'error',
        message: res.message,
        duration: 5000
      });
    }

    // 401 : Token非法或过期;
    if (response.status === 401 || res.code === 401) {
      MessageBox.confirm('当前登录已过期，请重新登录', '', {
        confirmButtonText: '重新登录',
        type: 'warning',
        center: true,
        showCancelButton: false,
        customClass: 'del-message',
        iconClass: 'del-icon'
      }).then(() => {
        store.dispatch('FedLogOut').then(() => {
          location.reload(); // 为了重新实例化vue-router对象 避免bug
        });
      }).catch(() => {
        store.dispatch('FedLogOut').then(() => {
          location.reload(); // 为了重新实例化vue-router对象 避免bug
        });
      });
      return res;
    }
    return Promise.reject({ message, code: res.code, data: res.data });
  } else {
    response.requestTime = new Date() - response.config.metadata.startTime;
    // 请求时间大于REQUEST_TIME，上报Sentry
    if (response.requestTime > REQUEST_TIME) {
      let message = '';
      /* message = `${response.config.url} interface is out of ${REQUEST_TIME / 1000}s`;
      if (/import/g.test(response.config.url) && response.requestTime > IMPORT_REQUEST_TIME) {
        message = `${response.config.url} interface is out of ${IMPORT_REQUEST_TIME / 1000}s`;
      } */
      message = `${response.config.url} interface is out of ${response.requestTime / 1000}s`;
      Raven.captureBreadcrumb({ category: 'console', message: JSON.stringify(params), level: 'log' });
      Raven.captureMessage(message, { level: 'info' });
    }
    return response.data;
  }
}, error => {
  console.error('Respone ' + error);
  if (error.message === 'Network Error') {
    ElMessage.warning('网络错误！请检查网络状态...');
    return Promise.reject({ message: '网络错误！请检查网络状态...' });
  }
  return Promise.reject(error);
});

export default service;
